﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.SweptVolume.CApSVAttachmentTraverse
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Tecnomatix.Engineering;
using Tecnomatix.Engineering.PrivateImplementationDetails;


namespace DnProcessSimulateCommands.SweptVolume;

public class CApSVAttachmentTraverse
{
  private ITxLocatableObject m_root;
  private HashSet<ITxObject> m_objectsCollected;
  private Queue<ITxObject> m_objectsInQueue;
  private TxTypeFilter m_locatableObjectsFilter;

  public CApSVAttachmentTraverse(ITxLocatableObject root) => this.m_root = root;

  public TxObjectList getAttachedObjects(bool shouldIncludeCable)
  {
    this.m_objectsCollected = new HashSet<ITxObject>();
    this.m_objectsInQueue = new Queue<ITxObject>();
    this.m_locatableObjectsFilter = new TxTypeFilter(typeof (ITxLocatableObject));
    List<ITxCable> cables = (List<ITxCable>) null;
    if (shouldIncludeCable)
      cables = new List<ITxCable>(TxCablePool.The.GetAllCables());
    this.addObject((ITxObject) this.m_root);
    while (this.m_objectsInQueue.Count != 0)
      this.visitChildren(this.m_objectsInQueue.Dequeue() as ITxLocatableObject);
    TxObjectList objectsList = new TxObjectList(this.m_objectsCollected.Count + (cables != null ? cables.Count : 0));
    foreach (ITxObject itxObject in this.m_objectsCollected)
    {
      if (this.isNeeded(itxObject))
        ((Collection<ITxObject>) objectsList).Add(itxObject);
      if (shouldIncludeCable && itxObject is TxFrame && cables != null && cables.Count > 0)
      {
        List<ITxCable> cablesToInsert = new List<ITxCable>();
        if (this.isCableAttachedTo(itxObject, cables, cablesToInsert))
        {
          for (int index = 0; index < cablesToInsert.Count; ++index)
          {
            ITxCable itxCable = cablesToInsert[index];
            if (this.isNeeded((ITxObject) itxCable))
              ((Collection<ITxObject>) objectsList).Add((ITxObject) itxCable);
          }
        }
      }
    }
    if (shouldIncludeCable && cables.Count != 0)
      this.addCableObjects(objectsList, cables);
    return objectsList;
  }

  private void addCableObjects(TxObjectList objectsList, List<ITxCable> cables)
  {
    foreach (ITxCable cable in cables)
    {
      if (this.isNeeded((ITxObject) cable) && TxFlxCableEx.LinkedRobot(cable) == this.m_root)
        ((Collection<ITxObject>) objectsList).Add((ITxObject) cable);
    }
  }

  private bool isCableAttachedTo(
    ITxObject obj,
    List<ITxCable> cables,
    List<ITxCable> cablesToInsert)
  {
    bool flag = false;
    if (obj is TxFrame)
    {
      for (int index = cables.Count - 1; index >= 0; --index)
      {
        if (cables[index].StartFrame == obj || cables[index].EndFrame == obj)
        {
          cablesToInsert.Add(cables[index]);
          cables.Remove(cables[index]);
          flag = true;
        }
      }
    }
    return flag;
  }

  private bool isNeeded(ITxObject obj)
  {
    if (obj is TxFrame)
      return false;
    ITxDisplayableObject displayableObject = obj as ITxDisplayableObject;
    bool flag = displayableObject != null;
    if (flag && displayableObject.Visibility - 2 <= 1)
    {
      switch (displayableObject)
      {
        case ITxComponent _:
        case ITxCompound _:
        case TxKinematicLink _:
          flag = true;
          break;
        default:
          flag = false;
          break;
      }
    }
    return flag;
  }

  private void visitChildren(ITxLocatableObject locObj)
  {
    foreach (ITxObject attachmentDescendant in (Collection<ITxObject>) locObj.GetDirectAttachmentDescendants((ITxTypeFilter) this.m_locatableObjectsFilter))
      this.addObject(attachmentDescendant);
    if (!(locObj is ITxObjectCollection))
      return;
    foreach (ITxObject directDescendant in (Collection<ITxObject>) (locObj as ITxObjectCollection).GetDirectDescendants((ITxTypeFilter) this.m_locatableObjectsFilter))
      this.addObject(directDescendant);
  }

  private void addObject(ITxObject obj)
  {
    if (!this.m_objectsCollected.Add(obj))
      return;
    this.m_objectsInQueue.Enqueue(obj);
  }
}
